# -*- coding: utf-8 -*-
"""
乒乓球培训管理系统 - 校区控制器

校区相关的业务逻辑处理
包括CRUD操作、数据验证、关联检查等
"""

import os
from datetime import datetime
from flask import current_app
from sqlalchemy import and_, or_, func
from werkzeug.utils import secure_filename
from app import db
from app.models.campus import Campus
from app.models.user import User
from app.models.table import Table
from app.models.reservation import Reservation


class CampusController:
    """校区控制器类"""

    @staticmethod
    def get_campus_list(page=1, per_page=10, keyword=None, status=None,
                       has_admin=None, sort_by='created_at_desc'):
        """
        获取校区列表（分页）

        Args:
            page: 页码
            per_page: 每页数量
            keyword: 搜索关键词
            status: 状态筛选
            has_admin: 管理员状态筛选
            sort_by: 排序方式

        Returns:
            tuple: (分页对象, 总数)
        """
        query = Campus.query

        # 关键词搜索
        if keyword:
            query = query.filter(
                or_(
                    Campus.name.contains(keyword),
                    Campus.address.contains(keyword),
                    Campus.description.contains(keyword)
                )
            )

        # 状态筛选
        if status:
            query = query.filter(Campus.status == status)

        # 管理员状态筛选
        if has_admin == 'yes':
            query = query.filter(Campus.admin_id.isnot(None))
        elif has_admin == 'no':
            query = query.filter(Campus.admin_id.is_(None))

        # 排序
        if sort_by == 'created_at_desc':
            query = query.order_by(Campus.created_at.desc())
        elif sort_by == 'created_at_asc':
            query = query.order_by(Campus.created_at.asc())
        elif sort_by == 'name_asc':
            query = query.order_by(Campus.name.asc())
        elif sort_by == 'name_desc':
            query = query.order_by(Campus.name.desc())
        elif sort_by == 'capacity_desc':
            query = query.order_by(Campus.capacity.desc())
        elif sort_by == 'capacity_asc':
            query = query.order_by(Campus.capacity.asc())

        pagination = query.paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )

        return pagination, pagination.total

    @staticmethod
    def get_campus_by_id(campus_id):
        """
        根据ID获取校区

        Args:
            campus_id: 校区ID

        Returns:
            Campus: 校区对象或None
        """
        return Campus.query.get(campus_id)

    @staticmethod
    def create_campus(form_data, photo_file=None):
        """
        创建校区

        Args:
            form_data: 表单数据
            photo_file: 上传的照片文件

        Returns:
            tuple: (是否成功, 校区对象或错误信息)
        """
        try:
            # 处理照片上传
            photo_url = None
            if photo_file and photo_file.filename:
                photo_url = CampusController._save_campus_photo(photo_file)
                if not photo_url:
                    return False, "照片上传失败"

            # 创建校区对象
            campus = Campus(
                name=form_data['name'],
                address=form_data['address'],
                phone=form_data['phone'],
                email=form_data.get('email'),
                admin_id=form_data.get('admin_id') if form_data.get('admin_id') else None,
                capacity=form_data['capacity'],
                area=form_data.get('area'),
                description=form_data.get('description'),
                facilities=form_data.get('facilities'),
                operating_hours=form_data.get('operating_hours'),
                photo_url=photo_url,
                status='active' if form_data.get('is_active', True) else 'inactive'
            )

            db.session.add(campus)

            # 如果分配了管理员，更新管理员的校区ID
            if campus.admin_id:
                admin = User.query.get(campus.admin_id)
                if admin:
                    admin.campus_id = campus.id

            db.session.commit()
            return True, campus

        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Create campus error: {str(e)}")
            return False, "创建校区失败，请重试"

    @staticmethod
    def update_campus(campus, form_data, photo_file=None):
        """
        更新校区

        Args:
            campus: 校区对象
            form_data: 表单数据
            photo_file: 上传的照片文件

        Returns:
            tuple: (是否成功, 错误信息)
        """
        try:
            old_admin_id = campus.admin_id

            # 处理照片上传
            if photo_file and photo_file.filename:
                photo_url = CampusController._save_campus_photo(photo_file)
                if photo_url:
                    # 删除旧照片
                    if campus.photo_url:
                        CampusController._delete_campus_photo(campus.photo_url)
                    campus.photo_url = photo_url

            # 更新校区信息
            campus.name = form_data['name']
            campus.address = form_data['address']
            campus.phone = form_data['phone']
            campus.email = form_data.get('email')
            campus.capacity = form_data['capacity']
            campus.area = form_data.get('area')
            campus.description = form_data.get('description')
            campus.facilities = form_data.get('facilities')
            campus.operating_hours = form_data.get('operating_hours')
            campus.status = 'active' if form_data.get('is_active', True) else 'inactive'
            campus.updated_at = datetime.now()

            # 处理管理员变更
            new_admin_id = form_data.get('admin_id') if form_data.get('admin_id') else None

            if old_admin_id != new_admin_id:
                # 清除旧管理员的校区关联
                if old_admin_id:
                    old_admin = User.query.get(old_admin_id)
                    if old_admin:
                        old_admin.campus_id = None

                # 设置新管理员的校区关联
                if new_admin_id:
                    new_admin = User.query.get(new_admin_id)
                    if new_admin:
                        new_admin.campus_id = campus.id

                campus.admin_id = new_admin_id

            db.session.commit()
            return True, None

        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Update campus error: {str(e)}")
            return False, "更新校区失败，请重试"

    @staticmethod
    def delete_campus(campus_id):
        """
        删除校区（软删除）

        Args:
            campus_id: 校区ID

        Returns:
            tuple: (是否成功, 错误信息)
        """
        try:
            campus = Campus.query.get(campus_id)
            if not campus:
                return False, "校区不存在"

            # 检查关联数据
            check_result = CampusController.check_campus_associations(campus_id)
            if not check_result['can_delete']:
                return False, check_result['message']

            # 执行软删除
            campus.status = 'deleted'

            # 清除管理员关联
            if campus.admin_id:
                admin = User.query.get(campus.admin_id)
                if admin:
                    admin.campus_id = None
                campus.admin_id = None

            db.session.commit()
            return True, None

        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Delete campus error: {str(e)}")
            return False, "删除校区失败，请重试"

    @staticmethod
    def check_campus_associations(campus_id):
        """
        检查校区关联数据

        Args:
            campus_id: 校区ID

        Returns:
            dict: 检查结果
        """
        # 检查用户数量
        user_count = User.query.filter_by(campus_id=campus_id).count()

        # 检查球台数量
        table_count = Table.query.filter_by(campus_id=campus_id).count()

        # 检查预约数量（未完成的）
        active_reservation_count = Reservation.query.join(Table).filter(
            and_(
                Table.campus_id == campus_id,
                Reservation.status.in_(['confirmed', 'in_progress'])
            )
        ).count()

        can_delete = user_count == 0 and active_reservation_count == 0

        associations = []
        if user_count > 0:
            associations.append(f"{user_count}个用户")
        if table_count > 0:
            associations.append(f"{table_count}个球台")
        if active_reservation_count > 0:
            associations.append(f"{active_reservation_count}个活跃预约")

        message = ""
        if not can_delete:
            message = f"无法删除，校区还有{', '.join(associations)}。请先处理这些关联数据。"

        return {
            'can_delete': can_delete,
            'user_count': user_count,
            'table_count': table_count,
            'active_reservation_count': active_reservation_count,
            'message': message
        }

    @staticmethod
    def get_campus_statistics(campus_id):
        """
        获取校区统计信息

        Args:
            campus_id: 校区ID

        Returns:
            dict: 统计信息
        """
        # 用户统计
        total_users = User.query.filter_by(campus_id=campus_id).count()
        active_students = User.query.filter(
            and_(User.campus_id == campus_id, User.role == 'student', User.status == 'active')
        ).count()
        active_coaches = User.query.filter(
            and_(User.campus_id == campus_id, User.role == 'coach', User.status == 'active')
        ).count()

        # 球台统计
        total_tables = Table.query.filter_by(campus_id=campus_id).count()
        available_tables = Table.query.filter(
            and_(Table.campus_id == campus_id, Table.status == 'available')
        ).count()

        # 预约统计（本月）
        from datetime import date
        today = date.today()
        month_start = today.replace(day=1)

        month_reservations = Reservation.query.join(Table).filter(
            and_(
                Table.campus_id == campus_id,
                Reservation.created_at >= month_start
            )
        ).count()

        return {
            'total_users': total_users,
            'active_students': active_students,
            'active_coaches': active_coaches,
            'total_tables': total_tables,
            'available_tables': available_tables,
            'month_reservations': month_reservations
        }

    @staticmethod
    def batch_operation(campus_ids, action):
        """
        批量操作校区

        Args:
            campus_ids: 校区ID列表
            action: 操作类型（activate/deactivate/delete）

        Returns:
            tuple: (成功数量, 失败数量, 错误信息列表)
        """
        success_count = 0
        fail_count = 0
        errors = []

        for campus_id in campus_ids:
            try:
                campus = Campus.query.get(campus_id)
                if not campus:
                    errors.append(f"校区ID {campus_id} 不存在")
                    fail_count += 1
                    continue

                if action == 'activate':
                    campus.status = 'active'
                    campus.updated_at = datetime.now()
                elif action == 'deactivate':
                    campus.status = 'inactive'
                    campus.updated_at = datetime.now()
                elif action == 'delete':
                    # 检查关联数据
                    check_result = CampusController.check_campus_associations(campus_id)
                    if not check_result['can_delete']:
                        errors.append(f"校区 {campus.name}: {check_result['message']}")
                        fail_count += 1
                        continue
                    campus.status = 'deleted'
                    campus.status = 'deleted'

                db.session.add(campus)
                success_count += 1

            except Exception as e:
                errors.append(f"校区ID {campus_id}: {str(e)}")
                fail_count += 1

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            return 0, len(campus_ids), [f"批量操作失败: {str(e)}"]

        return success_count, fail_count, errors

    @staticmethod
    def _save_campus_photo(photo_file):
        """
        保存校区照片

        Args:
            photo_file: 上传的文件对象

        Returns:
            str: 照片URL或None
        """
        try:
            # 确保上传目录存在
            upload_dir = os.path.join(current_app.root_path, 'static', 'uploads', 'campus')
            os.makedirs(upload_dir, exist_ok=True)

            # 生成安全的文件名
            filename = secure_filename(photo_file.filename)
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"campus_{timestamp}_{filename}"

            # 保存文件
            photo_path = os.path.join(upload_dir, filename)
            photo_file.save(photo_path)

            return f"/static/uploads/campus/{filename}"

        except Exception as e:
            current_app.logger.error(f"Save campus photo error: {str(e)}")
            return None

    @staticmethod
    def _delete_campus_photo(photo_url):
        """
        删除校区照片

        Args:
            photo_url: 照片URL
        """
        try:
            if photo_url and photo_url.startswith('/static/uploads/campus/'):
                photo_path = os.path.join(
                    current_app.root_path,
                    photo_url.lstrip('/')
                )
                if os.path.exists(photo_path):
                    os.remove(photo_path)
        except Exception as e:
            current_app.logger.error(f"Delete campus photo error: {str(e)}")